#include <54func.h>
//实现：A先执行，B再执行
typedef struct shareRes_s{
    int flag;//标志位：0--->A未写，1--->A已写
    pthread_mutex_t mutex;
    pthread_cond_t cond;//条件变量
}shareRes_t;
void A()
{
    printf("Before A\n");
    sleep(3);
    printf("After A\n");
}
void B()
{
    printf("Befor B\n");
    sleep(3);
    printf("After B\n");
}
void *threadFunc(void *arg)
{
    shareRes_t *pshareRes = (shareRes_t *)arg;

    //循环等待，查看标志位是否被置为1，该过程的缺点就是一直占用消耗资源，可以改为阻塞，进而引出“条件变量”
//   while(1)
//   {
//       pthread_mutex_lock(&pshareRes->mutex); 
//       if(pshareRes->flag == 1)
//       {
//           pthread_mutex_unlock(&pshareRes->mutex);
//           break;
//       }
//       pthread_mutex_unlock(&pshareRes->mutex);
//   }
    
    //使用条件变量来实现阻塞，从而防止while一直占用cpu
    pthread_mutex_lock(&pshareRes->mutex);//读取共享资源仍然是需要加锁的！！！
    if(pshareRes->flag == 0)//判断如果标志位没有被修改，说明A还未执行完全，则等待
    {
        //wait原理：检查mutex存在->将线程移入到唤醒队列->解开锁并陷入等待（解锁和等待是原子操作）
        pthread_cond_wait(&pshareRes->cond,&pshareRes->mutex);
       //被唤醒，加锁-->带着锁返回-->因此在wait操作之后不需要在解锁

        // pthread_mutex_unlock(&pshareRes->mutex);不需要这一步，因为wait的底层原理中，会解锁并等待
    }
    pthread_mutex_unlock(&pshareRes->mutex);
    
    //跳出上述循环，说明A已经执行完成，且将标志位设置为 1
    B();
    pthread_exit(NULL);
}
int main()
{
    shareRes_t shareRes;//定义一个结构体
    shareRes.flag = 0;//初始化标志位
    pthread_cond_init(&shareRes.cond,NULL);                  //条件变量的初始化
    pthread_t tid;
    pthread_mutex_init(&shareRes.mutex,NULL);//初始化锁
    pthread_create(&tid,NULL,threadFunc,&shareRes);//创建子线程

    sleep(2);

    A();
    //A执行结束后，将标志位设置未1，但是因为标志位是共享资源，因此需要对其进行加锁
    pthread_mutex_lock(&shareRes.mutex);
    shareRes.flag = 1;
    //修改完条件后，发送一个通知请求
    pthread_cond_signal(&shareRes.cond);
    pthread_mutex_unlock(&shareRes.mutex);
    pthread_join(tid,NULL);
    return 0;
}
